import axios from 'axios';

const BASE_URL = '';

export default function request(url, options) {
  const token = localStorage.getItem('token');
  const defaultOptions = {
    headers: {
      Authorization: `Bearer ${token}`,
    },
    withCredentials: true,
    url: url,
    baseURL: BASE_URL,
  };

  const newOptions = { ...options, ...defaultOptions };

  return axios
    .request(newOptions)
    .then((res) => {
      checkStatus(res);
    })
    .catch((err) => {
      console.log(err);
      throw Error(err);
    });
}

// 封装了一个检测返回结果的函数，与后台返回状态码code === 1002表示token失效
let isRefreshing = true;
function checkStatus(response) {
  if (response?.code === 1002) {
    // 刷新token的函数, 添加一个开关，防止重复请求
    if (isRefreshing) {
      refreshTokenRequst();
    }
    isRefreshing = false;

    // 这个Promise函数很关键
    const retryOriginalRequest = new Promise((resolve) => {
      addSubscriber(() => {
        resolve(request(url, options));
      });
    });

    return retryOriginalRequest;
  }

  return response;
}

// 刷新token的请求函数
function refreshTokenRequst() {
  const refreshToken = localStorage.getItem('refreshToken');
  let data = {
    authorization: 'YXBwYXBpczpaSWxhQUVJdsferTeweERmR1praHk=',
    refreshToken,
  };

  axios
    .request({
      baseURL: BASE_URL,
      url: '/api/refreshToken',
      method: 'POST',
      data,
    })
    .then((res) => {
      localStorage.setItem('refreshToken', res?.data?.refreshToken);
      localStorage.setItem('token', res?.data?.token);
      onAccessTokenFetched();
      isRefreshing = true;
    });
}

// Promise函数集合
let subscribers = [];
function onAccessTokenFetched() {
  subscribers.forEach((callback) => {
    callback();
  });
  subscribers = [];
}

function addSubscriber(callback) {
  subscribers.push(callback);
}

// 总结：其实token失效，自动刷新token，在页面只有一个请求的时候是比较好处理的，
// 但是如果页面同时有多个请求，并且都会产生token失效，这就需要一些稍微复杂的处理，
// 解决方式主要是用了Promise 函数来进行处理。每一个token失效的请求都会存到一个Promise函数集合里面，
// 当刷新token的函数执行完毕后，才会批量执行这些Promise函数，返回请求结果。还有一点要注意一下，
// 这儿设置一个刷新token的开关isRefreshing，这个是非常有必要的，防止重复请求。
